home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / tex / cut_past.zip / CUT.C next >
Text File  |  1987-03-05  |  5KB  |  255 lines

  1. /*
  2.  *  This acts the same as SV cut(1), except that the list of numbers
  3.  *  does not have to be assending.
  4.  *
  5.  * John Weald
  6.  */
  7. #include <stdio.h>
  8. /* #include <ctype.h> */
  9.  
  10. #define MAXLINE    1024        /* The max. length of a line        */
  11.  
  12. extern exit();
  13.  
  14. main(argc, argv)
  15. int argc;
  16. char *argv[];
  17. {
  18.     extern char *optarg;
  19.     extern int optind;
  20.  
  21.     static int fields[MAXLINE];/* The field markers. True if this field */
  22.                    /* is to be cut, False otherwise    */
  23.     FILE *fp;           /* All the input files or stdin    */
  24.     char buf[MAXLINE];       /* The input buffer            */
  25.     int c;               /* The command line option        */
  26.     int err = 0;           /* True if error in command line    */
  27.     int fflag = 0;           /* True if -f on command line    */
  28.     int cflag = 0;           /* True if -c on command line    */
  29.     int suppress = 0;       /* Suppress lines with no delimitor    */
  30.     char fs = '\t';           /* The field separator        */
  31.  
  32.     
  33.     while ((c = getopt(argc, argv, "f:d:c:s", "cut")) != EOF)
  34.     {
  35.         switch (c)
  36.         {
  37.            case 'f':
  38.             /* By Field */
  39.             list(fields, optarg);
  40.             fflag++;
  41.             if (cflag)
  42.                 err++;
  43.             break;
  44.  
  45.            case 'c':
  46.             /* By character */
  47.             list(fields, optarg);
  48.             /* Implied suppress */
  49.             suppress++;
  50.             cflag++;
  51.             if (fflag)
  52.                 err++;
  53.             break;
  54.  
  55.            case 'd':
  56.             /* A new field spererator */
  57.             fs = *optarg;
  58.             break;
  59.  
  60.            case 's':
  61.             suppress++;
  62.             break;
  63.  
  64.            default:
  65.             prusage();
  66.         }
  67.     }
  68.  
  69.     if (!cflag && !fflag)
  70.     {
  71.         fprintf(stderr, "Must have one of -f or -c\n");
  72.         err++;
  73.     }
  74.     if (err)
  75.         prusage();
  76.  
  77.  
  78.     /*
  79.      * Loop on all the files.
  80.      */
  81.     do {
  82.         if (optind == argc)
  83.             fp = stdin;
  84.         else if ((fp = fopen(argv[optind], "r")) == (FILE *)NULL)
  85.         {
  86.             fprintf(stderr, "Failed to open file %s\n", 
  87.                     argv[optind]);
  88.             exit(1);
  89.         }
  90.  
  91.         /*
  92.          * Loop on all lines in the file.
  93.          */
  94.         while (fgets(buf, sizeof(buf), fp) != (char *)NULL)
  95.         {
  96.             cut(buf, fields, fs, suppress, cflag);
  97.         }
  98.         fclose(fp);
  99.     } while (++optind < argc);
  100.  
  101.     exit(0);
  102. /* NOTREACHED */
  103. }
  104.  
  105. /*
  106.  * Cut the line. This handles both character and field cutting.
  107.  * For character cutting the f array gives character positions, for
  108.  * fields it gives the field number. It must be indexed by either the
  109.  * character number or the field number.
  110.  */
  111. cut(in, f, fs, sup, c_or_f)
  112. register char *in;        /* The input line            */
  113. int f[];            /* The field cutting flags        */
  114. char fs;            /* The field seperator            */
  115. int sup;            /* Suppress lines with no-delimitor?    */
  116. int c_or_f;            /* Cut by char. (true), or field (false)*/
  117. {
  118.     char obuf[MAXLINE];    /* Output buffer            */
  119.     register char *optr = obuf;
  120.     register int i;        /* Character count            */
  121.     register int fld;    /* The field count            */
  122.     char *instart = in;    /* To print lines with no delimiters    */
  123.  
  124.     for (fld = 0, i = 0; i < MAXLINE; i++)
  125.     {
  126.         if (*in == '\n')
  127.         {
  128.             /* End of the line */
  129.  
  130.             *optr = '\0';
  131.             /* Any thing to cut? */
  132.             if (optr != obuf)
  133.             {
  134.                 /* Get ride of trailing seperator */
  135.                 if (*(optr - 1) == fs)
  136.                     *(optr - 1) = '\0';
  137.                 puts(obuf);
  138.             }
  139.             else if (!sup)
  140.                 printf(instart);
  141.             return;
  142.         }
  143.  
  144.         if (f[c_or_f ? i : fld])
  145.         {
  146.             *optr++ = *in;
  147.         }
  148.  
  149.         /* End of field? */
  150.         if (*in++ == fs)
  151.             fld++;
  152.     }
  153.  
  154.     fprintf(stderr, "Line too long, maximum length is %d\n", MAXLINE);
  155.     exit(1);
  156. }
  157.  
  158. /*
  159.  * Parse the list argument. The format is:
  160.  *    n,n
  161.  * where n is either a number or a range of numbers in the format
  162.  *    m-l
  163.  * m or l  may be absent, indicating the start or end of the lines respectivly.
  164.  * Numbers must be in increasing order for m-l format, but not for n,n.
  165.  * Field numbers start at 1, but index into fields array starts at 0.
  166.  * 
  167.  */
  168. list(f, l)
  169. int f[];        /* The fields                */
  170. char *l;        /* The list                */
  171. {
  172.     int range = 0;    /* True if m-l format             */
  173.     int low, high;    /* the low and high numbers in a m-l pair*/
  174.     int i;
  175.  
  176.     low = high = 0;
  177.  
  178.     while (1)
  179.     {
  180.         switch(*l)
  181.         {
  182.            case '\0':
  183.             /* Is it m-<nothing>EOL? */
  184.             if (range)
  185.             {
  186.                 /* Select rest of fields */
  187.                 for(i = low - 1; i < MAXLINE; i++)
  188.                     f[i]++;
  189.             }
  190.             else
  191.                 f[low-1]++;
  192.             return;
  193.  
  194.            case ',':
  195.             l++;
  196.             if (!range)
  197.                 f[low-1]++;
  198.             range = 0;
  199.             low = 1;
  200.             break;
  201.  
  202.            case '-':
  203.             l++;
  204.             range++;
  205.             /* Is it m-<nothing> */
  206.             if (isdigit((int)*l))
  207.             {
  208.                 high = atoi(l);
  209.                 /* Skip the digits */
  210.                 while (isdigit((int) *l))
  211.                     l++;
  212.                 range = 0;    /* Range bug fix -- GDE */
  213.             }
  214.             else
  215.                 high = MAXLINE;
  216.  
  217.             /* Is the range the correct way around? */
  218.             if (low > high)
  219.             {
  220.                 fprintf(stderr, "Bad c/f list: %d > %d\n", 
  221.                             low, high);
  222.                 exit(1);
  223.             }
  224.             /* Set the field flags for the range */
  225.             for(i = low - 1; i < high; i++)
  226.                 f[i]++;
  227.             break;
  228.  
  229.             default:
  230.             /* either a number or an error */
  231.             if (!isdigit((int) *l))
  232.             {
  233.                 fprintf(stderr, "Bad c/f list at %s\n", l);
  234.                 exit(1);
  235.             }
  236.             low = atoi(l);
  237.             if (low == 0)
  238.             {
  239.                 fprintf(stderr, "Fields start at 1 not 0\n");
  240.                 exit(1);
  241.             }
  242.             /* Skip the digits */
  243.             while (isdigit((int) *l))
  244.                 l++;
  245.             break;
  246.         }
  247.     }
  248. }
  249.  
  250. prusage()
  251. {
  252.     fprintf(stderr, "cut [-d<delimitor>] [-s] -c<list>|-f<list> [files]\n");
  253.     exit(1);
  254. }
  255.